package Model;

import java.util.ArrayList;

/**
 * This class contains the coordinates of an object on the map
 */
public class Location 
{
    // ATTRIBUTE

    private int xPosition;
    private int yPosition;

    // CONSTRUCTOR
    public Location(int x, int y) 
    {
        this.xPosition = x;
        this.yPosition = y;
    }

    // OWN FUNCTIONS
    public ArrayList<Direction> getRelativeDirection(Location location) 
    {
        ArrayList<Direction> res = new ArrayList<Direction>();

        if ( this.xPosition < location.getXPosition() ) // the location is on east from this.
        {
            res.add(Direction.East);
        }

        if ( this.xPosition > location.getXPosition() ) // the location is on West from this.
        {
            res.add(Direction.West);
        }

        if ( this.yPosition < location.getYPosition() ) // the location is on South from this.
        {
            res.add(Direction.South);
        }

        if ( this.yPosition > location.getYPosition() ) // the location is on North from this.
        {
            res.add(Direction.North);
        }

        return res;
    }

    public int getRelativeDistance(Location location) 
    {
        // square norm
        int res = 0;
        int xToCompare = location.getXPosition();
        int yToCompare = location.getYPosition();
        
        if ( Math.abs(xToCompare - this.xPosition) > Math.abs(yToCompare - this.yPosition) ) 
        {
            res = Math.abs(xToCompare - this.xPosition);
        }
        else 
        {
            res = Math.abs(yToCompare - this.yPosition);
        }
        return res;
    }

    public boolean compare(Location loc) 
    {
    	return (loc.getXPosition() == this.getXPosition()) && (loc.getYPosition() == this.getYPosition());
    }
    
    public ArrayList<DirectionWeighted> getRelativeDirectionWeighted(Location location) 
    {
        ArrayList<DirectionWeighted> res = new ArrayList<DirectionWeighted>();
        ArrayList<Direction> resAux = getRelativeDirection(location);
        int weight = getRelativeDistance(location);
        for ( int i = 0; i < resAux.size(); i++ ) 
        {
            res.add(new DirectionWeighted(resAux.get(i), weight));
        }
        return res;
    }

    public DirectDirection whatDirectDirectionWith(Location location) 
    {
        DirectDirection res = null;
       
        if ((this.xPosition > location.getXPosition()) && (this.yPosition > location.getYPosition())) 
        {
            res = DirectDirection.NorthWest;
        } 
        else if ((this.xPosition == location.getXPosition()) && (this.yPosition > location.getYPosition())) {
            res = DirectDirection.North;
        } 
        else if ((this.xPosition < location.getXPosition()) && (this.yPosition > location.getYPosition())) 
        {
            res = DirectDirection.NorthEast;
        } 
        else if ((this.xPosition > location.getXPosition()) && (this.yPosition == location.getYPosition())) 
        {
            res = DirectDirection.West;
        }
        else if ((this.xPosition < location.getXPosition()) && (this.yPosition == location.getYPosition()))
        {
            res = DirectDirection.East;
        } 
        else if ((this.xPosition > location.getXPosition()) && (this.yPosition < location.getYPosition()))
        {
            res = DirectDirection.SouthWest;
        } 
        else if ((this.xPosition == location.getXPosition()) && (this.yPosition < location.getYPosition()))
        {
            res = DirectDirection.South;
        } 
        else if ((this.xPosition < location.getXPosition()) && (this.yPosition < location.getYPosition()))
        {
            res = DirectDirection.SouthEast;
        } 
        else if ((this.xPosition == location.getXPosition()) && (this.yPosition == location.getYPosition())) 
        {
        	res = DirectDirection.None;
        }
        
        //Cas ou this = location, + d'autres cas ?
        if( res == null )
        {     
            System.out.println("%%%%%%%% ERROR whatDirectDirectionWith %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
            System.out.println("Direction direction non trouvée entre les 2 locations suivantes : ");
            System.out.println("Location param : "+ location.toString());
            System.out.println("Location this" + this.toString());
            System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
        }
        return res;
    }

            @Override
        public int hashCode()
        {
            int hash = 17;
            hash = 31*hash + this.xPosition;
            hash = 31*hash + this.yPosition;
            return hash;
        }
    
    
    
    public Location getLocationInDirectDirection(DirectDirection dd)
    {
    	Location res = new Location(xPosition,yPosition);
    	switch ( dd )
    	{
    		case NorthWest:
    			res.setXPosition(xPosition-1);
    			res.setYPosition(yPosition-1);
    			break;
    		case North:
    			res.setYPosition(yPosition-1);
    			break;
    		case NorthEast:
    			res.setXPosition(xPosition+1);
    			res.setYPosition(yPosition-1);
    			break;
    		case West:
    			res.setXPosition(xPosition-1);
    			break;
    		case East:
    			res.setXPosition(xPosition+1);
    			break;
    		case SouthWest:
    			res.setXPosition(xPosition-1);
    			res.setYPosition(yPosition+1);
    			break;
    		case South:
    			res.setYPosition(yPosition+1);
    			break;
    		case SouthEast:
    			res.setXPosition(xPosition+1);
    			res.setYPosition(yPosition+1);
    			break;
    		default:
    			break;
    	}
    	return res;
    }
    public void displayInTerminal() 
    {
    	System.out.println("x = " + this.xPosition+ " - "+ "y = " + this.yPosition);
    }

    public String toString() 
    {
         String s = "x = " + this.xPosition+ " - "+ "y = " + this.yPosition;
         return s;
    }
    // GETTER - SETTER
    public int getXPosition() 
    {
        return this.xPosition;
    }

    public int getYPosition() 
    {
        return this.yPosition;
    }

    public void setXPosition(int x) 
    {
        this.xPosition = x;
    }

    public void setYPosition(int y) 
    {
        this.yPosition = y;
    }
}
